// Fill out your copyright notice in the Description page of Project Settings.


#include "NPCAreaBaseCpp.h"
#include "GameInstanceBaseCpp.h"
#include "GamingUICpp.h"
#include "NPCBaseCpp.h"

// Sets default values
ANPCAreaBaseCpp::ANPCAreaBaseCpp()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	Area = CreateDefaultSubobject<UBoxComponent>(TEXT("Area"));
	Area->SetSimulatePhysics(false);
	Area->SetGenerateOverlapEvents(true);
	RootComponent = Area;
	Player = nullptr;
	Tags.Add(FName("NPCArea"));
}

// Called when the game starts or when spawned
void ANPCAreaBaseCpp::BeginPlay()
{
	Super::BeginPlay();

	FScriptDelegate StartOverlapDelegate;
	StartOverlapDelegate.BindUFunction(this, "OnPlayerOverlapStart");
	Area->OnComponentBeginOverlap.Add(StartOverlapDelegate);

	FScriptDelegate EndOverlapDelegate;
	EndOverlapDelegate.BindUFunction(this, "OnPlayerOverlapEnd");
	Area->OnComponentEndOverlap.Add(EndOverlapDelegate);
}

// Called every frame
void ANPCAreaBaseCpp::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ANPCAreaBaseCpp::RegisterToNPCsState(ANPCBaseCpp* const NPC)
{
	if (!NPCsState.Contains(NPC))
	{
		NPCsState.Add(NPC, true);
	}
}

void ANPCAreaBaseCpp::UpdateNPCsState(const ANPCBaseCpp* NPC)
{
	if (NPCsState.Contains(NPC))
	{
		NPCsState[NPC] = false;
	}
}

void ANPCAreaBaseCpp::SetAreaSize(const float WConfig, const float HConfig)
{
	W = WConfig;
	H = HConfig;
	Area->InitBoxExtent(FVector(W, 32.0, H));
	Area->SetBoxExtent(FVector(W, 32.0, H));
}

void ANPCAreaBaseCpp::Notify(const bool PlayerInArea)
{
	TArray<ANPCBaseCpp*> KeyArray;
	NPCsState.GenerateKeyArray(KeyArray);
	for (ANPCBaseCpp* N : KeyArray)
	{
		if (NPCsState[N] && IsValid(N))
		{
			if (PlayerInArea)
			{
				if (N->ActorHasTag(FName("Demon")))
				{
					N->NotifyNPCOnChangingActionState(ENPCAction::E_Attack1);
					UGameInstanceBaseCpp* CurrentGameInstance = Cast<UGameInstanceBaseCpp>(GetGameInstance());
					UGamingUICpp* GamingUI = Cast<UGamingUICpp>(CurrentGameInstance->GetMenuUI());
					GamingUI->GetNPCHPSlider()->SetVisibility(ESlateVisibility::Visible);
					GamingUI->SetDemon(N);
				}
				else
				{
					N->NotifyNPCOnChangingActionState(ENPCAction::E_Run);
				}
			}
			else
			{
				if (N->ActorHasTag(FName("Demon")))
				{
					N->NotifyNPCOnChangingActionState(ENPCAction::E_Idle);
					UGameInstanceBaseCpp* CurrentGameInstance = Cast<UGameInstanceBaseCpp>(GetGameInstance());
					UGamingUICpp* GamingUI = Cast<UGamingUICpp>(CurrentGameInstance->GetMenuUI());
					GamingUI->GetNPCHPSlider()->SetVisibility(ESlateVisibility::Collapsed);
					GamingUI->SetDemon(nullptr);
				}
				else
				{
					N->NotifyNPCOnChangingActionState(ENPCAction::E_Walk);
				}
			}
		}
		else
		{
			NPCsState.Remove(N);
		}
	}
}

void ANPCAreaBaseCpp::OnPlayerOverlapStart(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor->ActorHasTag(FName("Player")))
	{
		Notify(true);
		Player = OtherActor;
	}
}

void ANPCAreaBaseCpp::OnPlayerOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (OtherActor->ActorHasTag(FName("Player")))
	{
		Notify(false);
		Player = nullptr;
	}
}

AActor* ANPCAreaBaseCpp::GetPlayerInArea() const
{
	return Player;
}

